<?php
/****************************************************
 *
 * @File: 	mld-newsletter.php
 * @Package:	MLD Newsletter
 * @Subject:	Main plugin file
 * @Date:	2 February 2012
 * @Revision:	1 june 2012
 * @Version:	0.9
 * @Status:	Beta
 * @Author:	Leen Moerland (www.leenmoerland.com)
 *
 * Changelog v0.3:
 * - added backwards compatibility for GS3.0
 * - changed back to Swiftmailer class for better email handling
 *
 * Changelog v0.4
 * - No newsletter send if email address not confirmed.
 * - Create new newsletter button works now.
 * - Added data handling class
 * - Create new data files when not present
 * - fixed issue with slashes in encoding (thanks to luis)
 * - include configration.php for GSVERSION check
 * 
 * Changelog v0.5
 * - Fixed bug in url construction (thanks to luis)
 * - Fixed bug in subscription procedure (thanks to luis)
 * - Fixed bug in saving email_confirm (thanks to luis)
 * - Fixed bug deleting letters
 * - Fixed bug saving send status
 * - Catch exeption when sending email
 * - added frontend newsletter archive functionality
 * 
 * Changelog v0.6
 * - Added filters for use in content
 * - Added option to send admin email to site admin
 * - Hide send to subscribers button when already send
 * 
 * Changelog v0.7
 * - Fixed minor bugs due to lack of testing the script
 * - Prevent the script from running twice
 * - Subscribeform result didn't show [FIXED]
 * - Required settings indicator [ADDED]
 * 
 * Changelog v0.8
 * - AntiFlood plugin swiftmailer to prevent flooding of the SMTP server [ADD]
 * - Bug in subscribe function [FIXED]
 * - csv import names and email [ADD]
 * - Bug in template footer image [FIXED IN CORE]
 * 
 * Changelog v0.9
 * - Make AntiFlood configurable [TODO]
 * - Split up plugin file into smaller files
 * - display sending emails progress [TODO]
*****************************************************/

// get correct id for plugin
$thisfile = basename(__FILE__, ".php");

// plugin registration
register_plugin(
    $thisfile, 
    'MLD Newsletter', 
    '0.9', 
    'Leen Moerland', 
    'http://www.leenmoerland.com/', 
    'Newsletter plugin for GS', 
    'mld-newsletter', 
    'newsletters'
);

//include config file if not present - since 0.4
if (file_exists(GSADMININCPATH . 'configuration.php')) {
    include_once GSADMININCPATH . 'configuration.php';
}

// add backwards compatibility - since 0.3
if (GSVERSION == 3.0) {
    include GSPLUGINPATH . 'mld-newsletter/compatibility.php';
}

// language support
i18n_merge('mld-newsletter') || i18n_merge('mld-newsletter', 'en_US');

//style support
if (GSVERSION > 3.0) {
    register_style('mld-newsletter-backstyle', $SITEURL . 'plugins/' . $thisfile . '/css/backstyle.css', '0.2', 'all');
    register_style('mld-newsletter-frontstyle', $SITEURL . 'plugins/' . $thisfile . '/css/frontstyle.css', '0.2', 'all');
    queue_style('mld-newsletter-backstyle', GSBACK);
    queue_style('mld-newsletter-frontstyle', GSFRONT);
} else {
    add_action('theme-header', 'addStyleBC', array(GSPLUGINPATH . 'mld-newsletter/css/frontstyle.css'));
    add_action('header', 'addStyleBC', array(GSPLUGINPATH . 'mld-newsletter/css/backstyle.css'));
}

//set the right function - since 0.3
$createNavTabFunction = 'createNavTab';
$createSideMenuFunction = 'createSideMenu';
if (GSVERSION == 3.0) {
    $createNavTabFunction = 'createNavTabBC';
    $createSideMenuFunction = 'createSideMenuBC';
}

//add actions
add_action('nav-tab', $createNavTabFunction, array('mld-newsletter', $thisfile, i18n_r('mld-newsletter/PLUGINNAME'), 'newsletters'));
add_action($thisfile . '-sidebar', $createSideMenuFunction, array($thisfile, i18n_r('mld-newsletter/MANAGELETTERS'), 'newsletters'));
add_action($thisfile . '-sidebar', $createSideMenuFunction, array($thisfile, i18n_r('mld-newsletter/MANAGESUBSCRIBERS'), 'subscribers'));
add_action($thisfile . '-sidebar', $createSideMenuFunction, array($thisfile, i18n_r('mld-newsletter/SETTINGS'), 'settings'));
add_action($thisfile . '-sidebar', $createSideMenuFunction, array($thisfile, i18n_r('mld-newsletter/EDITLETTER'), 'editletter', false));
add_action($thisfile . '-sidebar', $createSideMenuFunction, array($thisfile, i18n_r('mld-newsletter/VIEWLETTER'), 'viewletter', false));
add_filter('content', 'mld_newsletter_parse');

//include data class - since 0.4
require GSPLUGINPATH . 'mld-newsletter/mldnewsletter.class.php';

/**
 * This function handles the request.
 * 
 */
function newsletters() {
    if (isset($_GET['settings'])) {
        include GSPLUGINPATH . 'mld-newsletter/newsletter_settings.php';
    } elseif (isset($_GET['subscribers'])) {
        include GSPLUGINPATH . 'mld-newsletter/manage_subscribers.php';
    } elseif (isset($_GET['editletter'])) {
        include GSPLUGINPATH . 'mld-newsletter/edit_letter.php';
    } elseif (isset($_GET['viewletter'])) {
        include GSPLUGINPATH . 'mld-newsletter/view_letter.php';
    } else {
        include GSPLUGINPATH . 'mld-newsletter/manage_newsletters.php';
    }
}

/**
 * This function handles the output filtering
 * 
 * @since 0.6
 * @param string $contents
 * @return string contents 
 */
function mld_newsletter_parse($contents) {
    //replace form
    $pattern = '`(?<!<code>)\(%\s*mldsubscribeform\s*(.*)\s*%\)`';
    $contents = preg_replace($pattern, mldNewsletterForm(true), $contents);
    
    //replace archive
    $pattern = '`(?<!<code>)\(%\s*mldnewsletterarchive\s*(.*)\s*%\)`';
    $contents = preg_replace($pattern, mldShowNewsletters(true), $contents);
    return $contents;
}

/**
 * Removes the newsletter.
 *
 * @param string $id newsletter id
 * @return array with message
 */
function remove_letter($id) {
    $mld = MLDnewsletter::getInstance();
    $xml = $mld->getXmlData('newsletters');
    foreach ($xml as $entry) {
        if ($entry->id == $id) {
            $dom = dom_import_simplexml($entry);
            $dom->parentNode->removeChild($dom);
            break;
        }
    }
    if (XMLsave($xml, $mld->files['newsletters'])) {
        $msg = array('updated', i18n_r('mld-newsletter/DELETESUCCES'));
    } else {
        $msg = array('error', i18n_r('mld-newsletter/DELETEFAIL'));
    }
    return $msg;
}

/**
 * Function to show subscribeform on frontpage
 *
 */
function mldNewsletterForm($buffer = false) {
    global $result;
    if (isset($_POST['subscribe'])) {
        $result = subscribe($_POST['subscriber']['name'], $_POST['subscriber']['email'], true);
        unset($_POST['subscribe']);
    } elseif (isset($_POST['unsubscribe'])) {
        $result = unsubscribe($_POST['subscriber']['email']);
        unset($_POST['unsubscribe']);
    } elseif (isset($_GET['emailconfirm'])) {
        $result = email_confirm($_GET['emailconfirm']);
        unset($_GET['emailconfirm']);
    }
    if ($buffer) {
        ob_start();
    }
    if (isset($result)) {
        echo '<div id="mldmessage" class="' . $result[0] . '">' . $result[1] . '</div>';
    }
    ?>                    
    	<form action="<?php get_page_url(); ?>" method="post" class="mldsubscribeform">
        <p><label class="mld_label"><?php i18n('mld-newsletter/NAME'); ?>:</label><input type="text" class="text" name="subscriber[name]" value=""/></p>        
        <p><label class="mld_label"><?php i18n('mld-newsletter/EMAIL'); ?>:</label><input type="text" class="text" name="subscriber[email]" value=""/></p>
        <p><input type="submit" class="submit" value="<?php i18n('mld-newsletter/SUBSCRIBE'); ?>" id="subscribe" name="subscribe" />
        <input type="submit" class="submit" value="<?php i18n('mld-newsletter/UNSUBSCRIBE'); ?>" id="unsubscribe" name="unsubscribe" /></p>
        </form>
    <?php
    if ($buffer) {
        $html = ob_get_contents();
        ob_end_clean();
        return $html;
    }
}

/**
 * Shows newsletter archive on website
 * 
 * @since 0.5
 */
function mldShowNewsletters($buffer = false) {
    $mld = MLDnewsletter::getInstance();
    $xml = $mld->getXmlData('newsletters');
    
    //check if form is submitted and load data
    $lettercontent = '<p>'.i18n_r('mld-newsletter/NOLETTERSELECTED').'</p>';
    if(isset($_POST['newsletters'])) {
        foreach($xml as $newsletter) {
            if((string) $newsletter->id == $_POST['newsletters']) {
                $lettercontent = (string) $newsletter->content;  
                break;
            }
        }
    }
    
    //load template header and footer
    $xmls = $mld->getXmlData('settings');
    $theader = (string) $xmls->theader;
    $tfooter = (string) $xmls->tfooter;
    
    if($buffer) { ob_start(); }
    ?>
    <h3><?php i18n('mld-newsletter/NEWSLETTERARCHIVE'); ?></h3>
    <form id="mld_selectNewsletter" class="mld_Form" method="post" action="<?php echo get_page_url(true); ?>">
        <label class="mld_label"><?php i18n('mld-newsletter/SELECTNEWSLETTER'); ?>:</label>
        <select name="newsletters" onchange="document.getElementById('mld_selectNewsletter').submit();">
            <option><?php i18n('mld-newsletter/SELECTNEWSLETTERFROMLIST'); ?></option>
            <?php            
                foreach($xml as $newsletter) {
                    if((string) $newsletter->send == 'true') {
                        echo '<option value="'.(string) $newsletter->id.'">'.(string) $newsletter->title.'</option>';                        
                    }                    
                }               
            ?>
        </select>
    </form>
    <div class="mld_newsletterpreview">
        <?php echo stripslashes(htmldecode($theader . $lettercontent . $tfooter)); ?>
    </div>
    <?php
    
    if($buffer) { 
         $html = ob_get_contents();
         ob_end_clean();
         return $html;
    }
}

/**
 * Confirm subscribed email address
 *
 * @param string $confirmcode
 * @return array with message
 */
function email_confirm($confirmcode) {
    $mld = MLDnewsletter::getInstance();
    $xml = $mld->getXmlData('subscribers');
    foreach ($xml as $entry) {
        if ((string) $entry->status == $confirmcode) {
            $entry->status = 'true';
            XMLsave($xml, $mld->files['subscribers']);
            return array('updated', i18n_r('mld-newsletter/SUBSCRIBESUCCES'));
        }
    }
    return array('error', i18n_r('mld-newsletter/CONFIRMATIONNOTFOUND'));
}

/**
 * Function to send emails.
 *
 * @param string $to_email
 * @param string $to_name
 * @param string $to_subject
 * @param string $to_message
 * @param boolean $batch
 * @return array with message
 */
function send_email($to_email, $to_name, $to_subject, $to_message, $batch = false) {
    $mld = MLDnewsletter::getInstance();
    $settingsxml = $mld->getXmlData('settings');
    require_once(GSPLUGINPATH . 'mld-newsletter/swift/swift_required.php');

    try {
        $SENDERNAME = (string) $settingsxml->sname;
        $SENDEREMAIL = (string) $settingsxml->semail;
        $SMTPSERVER = (string) $settingsxml->smtpserver;
        $SMTPPORT = (int) $settingsxml->smtpport;
        $SMTPAUTH = (string) $settingsxml->smtpauth;
        $SMTPSECURE = (string) $settingsxml->smtpsecure;
        $SMTPAUTHNAME = (string) $settingsxml->smtpauthname;
        $SMTPAUTHPW = (string) $settingsxml->smtpauthpw;

        $to_message = stripslashes($to_message);

        $mail = Swift_Message::newInstance()
                ->setSubject($to_subject)
                ->setFrom(array($SENDEREMAIL => $SENDERNAME))
                ->setBody((string) $to_message, 'text/html')
        ;

        //set transport
        $transport = Swift_SmtpTransport::newInstance($SMTPSERVER, (int) $SMTPPORT);
        if ($SMTPAUTH == true) {
        $transport->setEncryption($SMTPSECURE);
        $transport->setUsername($SMTPAUTHNAME);
        $transport->setPassword($SMTPAUTHPW);
        }

        $mailer = $mailer = Swift_Mailer::newInstance($transport);

        //add receipients
        if ($batch == true) {
            $mailer->registerPlugin(new Swift_Plugins_AntiFloodPlugin(100, 30));
            $numSent = 0;
            foreach ($to_email as $email => $name) {
                $mail->setTo(array((string) $email => $name));
                $numSent += $mailer->send($mail);
                    }
            if($numSent > 0) {
                return array('updated', i18n_r('mld-newsletter/SENDSUCCESS').' ('.(string) $numSent.')');
            } else {
                return array('error', i18n_r('mld-newsletter/SENDFAIL'));
            }
        } else {
            $mail->setTo(array((string) $to_email => $to_name));
            if ($mailer->send($mail) > 0) {
                return array('updated', i18n_r('mld-newsletter/SENDSUCCESSADMIN').$to_email);
            } else {
                return array('error', i18n_r('mld-newsletter/SENDFAILADMIN').$to_email);
            }
        }
    } catch (Exception $e) {
        return array('error', $e->getMessage());
        //echo $e->getMessage();
    }
}

/**
 * Subscribe email addresses
 *
 * @param string $name
 * @param string $email
 * @param boolean $confirm whether the subscribtion needs confirmation or not.
 * @return array with message
 */
function subscribe($name, $email, $confirm = true) {
    $mld = MLDnewsletter::getInstance();
    $error = array();
    $xml = $mld->getXmlData('subscribers');


    //check for valid email and duplication
    if (!check_email_address($email)) {
        $error = i18n_r('mld-newsletter/WRONGEMAIL');
    } else {
        foreach ($xml as $entry) {
            if ($entry->email == $email && $entry->status == 'true') {
                $error = i18n_r('mld-newsletter/ALREADYREGISTERED');
            } elseif ($entry->email == $email && $entry->status != 'true') {
                if($confirm == true) {
                    //send confirm email again
                    $error = sendConfirmEmail($entry->name, $entry->email, $entry->status, true);                                        
                } else {                    
                    return email_confirm($entry->status);                    
                }
            }
        }
    }

    if (count($error) == 0) {
        if ($confirm == true) {
            $confirmcode = uniqid();
        } else {
            $confirmcode = 'true';
        }

        $newentry = $xml->addChild('entry');
        $temp = $newentry->addChild('name');
        $temp->addCData($name);
        $temp = $newentry->addChild('email');
        $temp->addCData($email);
        $temp = $newentry->addChild('status', $confirmcode);
        XMLsave($xml, $mld->files['subscribers']);

        if ($confirm == true) {
            //send confirm email again
            $msg = sendConfirmEmail($newentry->name, $newentry->email, $newentry->status, false);             
        } else {
            $msg = array('updated', i18n_r('mld-newsletter/SUBSCRIBESUCCES'));
        }
        return $msg;
    } else {
        $msg = array('error', $error);
    }
    return $msg;
}

/**
 * Send confirmation email
 * 
 * @param string $name
 * @param string $email
 * @param string $status
 * @param boolean $again
 * @return array or string 
 */
function sendConfirmEmail($name, $email, $status, $again = false) {
    // Checking if the URL has arguments yet (has '?').
    if (strpos(get_page_url(true), '?')) {
        $confirmurl = get_page_url(true) . '&emailconfirm=' . $status;
    } else {
        $confirmurl = get_page_url(true) . '?&emailconfirm=' . $status;
    }
    $message = '<h3>' . i18n_r('mld-newsletter/CONFIRMEMAILTITLE') . '</h3>' . i18n_r('mld-newsletter/CONFIRMEMAILBODY1')
            . '<br />Name: ' . $name . '<br />Email: ' . $email . '<br />' . i18n_r('mld-newsletter/CONFIRMEMAILBODY2') . ' <a href="' . $confirmurl . '">'
            . $confirmurl . '</a>';
    $emailresult = send_email($email, $name, i18n_r('mld-newsletter/CONFIRMEMAILSUBJECT'), $message);
    if ($emailresult[0] != 'error' && $again == false) {
        return array('updated', i18n_r('mld-newsletter/CONFIRMATIONSEND'));
    } elseif ($emailresult[0] != 'error' && $again == true) {
        return i18n_r('mld-newsletter/CONFIRMAGAIN');
    } elseif ($again == false) {
        return array('error', i18n_r('mld-newsletter/SUBSCRIBEFAIL'));
    } else {
        return i18n_r('mld-newsletter/SUBSCRIBEFAIL');
    }
}

/**
 * Remove email address from file
 *
 * @param string $email
 * @return array with message
 */
function unsubscribe($email) {
    $mld = MLDnewsletter::getInstance();
    $xml = $mld->getXmlData('subscribers');
    $found = false;
    foreach ($xml as $entry) {
        if ($entry->email == $email) {
            $dom = dom_import_simplexml($entry);
            $dom->parentNode->removeChild($dom);
            $found = true;
            break;
        }
    }

    if ($found == true) {
        if (!XMLsave($xml, $mld->files['subscribers'])) {
            $msg = array('error', i18n_r('mld-newsletter/SAVEFAIL'));
        } else {
            $msg = array('updated', i18n_r('mld-newsletter/UNSUBSCRIBESUCCES'));
        }
    } else {
        $msg = array('error', i18n_r('mld-newsletter/EMAILNOTFOUND'));
    }

    return $msg;
}

/**
 * Show message.
 *
 * @param string $type gives type of message
 * @param string $text message text
 */
function display_message($type, $text) {
    ?>
    	<script type="text/javascript">
            $(function() {
                $('div.bodycontent').before('<div class="<?php echo $type; ?>" style="display:block;">'+
                    <?php echo json_encode($text); ?>+'</div>');
                    $(".updated, .error").fadeOut(500).fadeIn(500);
            });
    	</script>
    <?php
}
?>